package com.hy.app.point;

import android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;

import com.hy.app.R;
import com.hy.app.utils.OpenGlUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * 顶点着色器等知识学习（绘制矩形）
 */
public class PointerRender implements GLSurfaceView.Renderer {
    /**
     * 位置顶点属性的大小
     * 包含(x,y)
     */
    private static final int VERTEX_POSITION_SIZE = 2;
    /**
     * 颜色顶点属性的大小
     * 包含(r,g,b)
     */
    private static final int VERTEX_COLOR_SIZE = 3;
    /**
     * 浮点型数据占用字节数
     */
    private static final int BYTES_PER_FLOAT = 4;

    /**
     * 跨距
     */
    //之前定义的坐标数据中，每一行是5个数据，前两个表示坐标(x,y)，后三个表示颜色(r,g,b)
    //所以这里实际是 STRIDE = (2 + 3) x 4
    private static final int VERTEX_ATTRIBUTE_SIZE =
            (VERTEX_POSITION_SIZE + VERTEX_COLOR_SIZE) * BYTES_PER_FLOAT;

    /**
     * 点的坐标
     */
    private static final float[] vertexPoints = new float[]{
            //前两个是坐标,后三个是颜色RGB
            0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
            0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
            0.5f, 0.5f, 1.0f, 1.0f, 1.0f,
            -0.5f, 0.5f, 1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, 1.0f, 1.0f, 1.0f,

            0.0f, 0.25f, 0.5f, 0.5f, 0.5f,
            0.0f, -0.25f, 0.5f, 0.5f, 0.5f,
    };

    private final FloatBuffer vertexBuffer;

    private final String vertexShader;
    private final String fragmentShader;

    public PointerRender(Context context) {
        //分配内存空间，每个浮点占4字节空间
        vertexBuffer = ByteBuffer.allocateDirect(vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //传入指定坐标数据
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);

        //获取顶点着色器和片元着色器
        vertexShader = OpenGlUtils.readRawShaderFile(context, R.raw.pointer_vertex_shader);
        fragmentShader = OpenGlUtils.readRawShaderFile(context, R.raw.pointer_fragment_shader);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //设置背景颜色
        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
        //编译
        int vertexShaderId = OpenGlUtils.compileVertexShader(vertexShader);
        int fragmentShaderId = OpenGlUtils.compileFragmentShader(fragmentShader);
        //链接
        int programId = OpenGlUtils.linkProgram(vertexShaderId, fragmentShaderId);
        GLES30.glUseProgram(programId);

        vertexBuffer.position(0);
        //获取顶点数组(VERTEX_POSITION_SIZE = 2)
        //每个顶点由size指定的顶点属性分量顺序存储。stride指定顶点索引I和(I+1），表示的顶点数据之间的位移。
        //如果stride为0，则每个顶点的属性数据顺序存储。如果stride大于0, 则使用该值作为获取下一个索引表示的顶点数据的跨距。
        GLES30.glVertexAttribPointer(0, VERTEX_POSITION_SIZE, GLES30.GL_FLOAT, false, VERTEX_ATTRIBUTE_SIZE, vertexBuffer);
        GLES30.glEnableVertexAttribArray(0);

        vertexBuffer.position(VERTEX_POSITION_SIZE);
        //颜色属性分量的数量(VERTEX_COLOR_SIZE = 3)
        GLES30.glVertexAttribPointer(1, VERTEX_COLOR_SIZE, GLES30.GL_FLOAT, false, VERTEX_ATTRIBUTE_SIZE, vertexBuffer);
        GLES30.glEnableVertexAttribArray(1);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
        //绘制矩形
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 6);
        //绘制两个点
        GLES30.glDrawArrays(GLES30.GL_POINTS, 6, 2);
    }
}
